/*
 * Copyright (c) 2021 com.youkeyi. All rights reserved.
 *
 *  @author liuxiawang
 *  @location Shenzhen.China
 *  @date 4/8/21 4:33 PM
 */

package com.youkeyi.ddy.cloud.common.interceptor;

import com.alibaba.fastjson.JSON;
import com.youkeyi.ddy.cloud.common.annotation.PassToken;
import com.youkeyi.ddy.cloud.common.constant.YoukeyiDdyApplicationSystemConstant;
import com.youkeyi.ddy.cloud.common.utils.RedisUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录验证拦截器
 *
 * @Author liuxiawang
 * @Date 2021-04-08 15:55
 * @Location shenzhen.china
 */
@Component
public class LoginValidateInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果不是映射到方法直接通过
        if(!(handler instanceof HandlerMethod)){
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod)handler;
        if (!handlerMethod.getBeanType().isAnnotationPresent(PassToken.class)) {
            Method method = handlerMethod.getMethod();
            // 检查是否有passtoken注解，有则跳过认证
            if (method.isAnnotationPresent(PassToken.class)) {
                PassToken passToken = method.getAnnotation(PassToken.class);
                if (passToken.required()) {
                    return true;
                }
            }
        } else {
            PassToken passToken = handlerMethod.getBeanType().getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }

        // 异常返回的数据
        OutputStream out = response.getOutputStream();
        Map<String, Object> resultMap = new HashMap<>();

        String token = request.getHeader("token");// 从 http 请求头中取出 token
        if (token == null) {
            response.setStatus(401);
            resultMap.put("code", "401");
            resultMap.put("message", "无Token，请重新登录");
            out.write(JSON.toJSONString(resultMap).getBytes());
            return false;
        }

        // 验证 token 是否存在，redis中存在就还在有效期内
        if (!RedisUtils.existKey(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_DB_INDEX, token)) {
            response.setStatus(401);
            resultMap.put("code", "401");
            resultMap.put("message", "无效Token，请重新登录");
            out.write(JSON.toJSONString(resultMap).getBytes());
            return false;
        }

        return super.preHandle(request, response, handler);
    }
}
